#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <syscall.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>


int main(void)
{
  long long counter = 0;  /*  machine instruction counter */
  int wait_val;           /*  child's return value        */
  int pid;                /*  child's process id          */

  puts("Please wait");

  switch (pid = fork()) {
  case -1:
    perror("fork");
    break;
  case 0: /*  child process starts        */
    ptrace(PTRACE_TRACEME, 0, 0, 0);
    /* 
     *  must be called in order to allow the
     *  control over the child process
     */ 
    execl("/bin/ls", "ls", NULL);
    /*
     *  executes the program and causes
     *  the child to stop and send a signal 
     *  to the parent, the parent can now
     *  switch to PTRACE_SINGLESTEP   
     */ 
    break;
    /*  child process ends  */
  default:/*  parent process starts       */
    wait(&wait_val); 
    /*   
     *   parent waits for child to stop at next 
     *   instruction (execl()) 
     */
    while (wait_val == 1407 ) {
      counter++;
      if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) != 0)
	perror("ptrace");
      /* 
       *   switch to singlestep tracing and 
       *   release child
       *   if unable call error.
       */
      wait(&wait_val);
      /*   wait for next instruction to complete  */
    }
    /*
     * continue to stop, wait and release until
     * the child is finished; wait_val != 1407
     * Low=0177L and High=05 (SIGTRAP)
     */
  }
  printf("Number of machine instructions : %lld\n", counter);
  return 0;
}
